import { ref, reactive, defineComponent } from 'vue'
import { ANY_DATA_TYPE } from '@/type'

enum PROMISE {
  padding = 'pending',
  fulfilled = 'fulfilled',
  rejected = 'rejected'
}
type FnAny<T> = (...arg: T[]) => void

interface Callback<T> {
  onResolved?: FnAny<T>,
  onRejected?: FnAny<T>
}
export class CustomPromise {
  _data: unknown = null
  _state = PROMISE.padding
  _callbacks: Callback<unknown>[] = []
  constructor (fn: unknown) {
    const resovle: FnAny<unknown> = (value) => {
      if (this._state === PROMISE.padding) {
        this._data = value
        this._state = PROMISE.fulfilled
        this._callbacks.forEach(({ onResolved }) => typeof onResolved === 'function' && onResolved(value))
      }
    }
    const reject: FnAny<unknown> = (error) => {
      if (this._state === PROMISE.padding) {
        this._data = error
        this._state = PROMISE.rejected
        this._callbacks.forEach(({ onRejected }) => typeof onRejected === 'function' && onRejected(error))
      }
    }
    try {
      typeof fn === 'function' && fn(resovle, reject)
    } catch (error) {
      reject(error)
    }
  }

  // then (onFulfilled: Function, onRejected: Function) {

  // }
}

type useCustomPromiseType = (fn: unknown) => CustomPromise

export const useCustomPromise: useCustomPromiseType = function (fn) {
  return new CustomPromise(fn)
}

export class customTest1 {
  a = 1
  public get () {
    return this.a
  }
}
export class customTest2 extends customTest1 {
  b = 2
  public get () {
    return this.b
  }
}
export const useState = (val: unknown) => {
  const value = ref(val)
  const setValue = (val: unknown) => {
    value.value = val
  }
  return [value, setValue]
}
// export const useRef = <T>(val: T) => {
//   const value = ref(val)
//   const setValue = (val: T) => {
//     value.value = val
//   }
//   return [value, setValue]
// }
export const useReactive = (param: ANY_DATA_TYPE) => {
  const state = reactive(param)
  const setValue = (key: ANY_DATA_TYPE | string, val: unknown) => {
    if (typeof key === 'string') {
      state[key] = val
    } else if (typeof key === 'object') {
      Object.assign(state, key)
    }
  }
  return [state, setValue]
}
/**
 * 使用页面
 */
export const useComp = (setup: (prop: unknown, context: unknown) => unknown, param?: ANY_DATA_TYPE) => {
  return defineComponent({
    ...param,
    setup
  })
}
